package services

import (
	"bbs-go/internal/consts"
	"bbs-go/internal/models/constants"
	"strconv"

	"github.com/mlogclub/simple/sqls"
	"github.com/mlogclub/simple/web/params"
	"gorm.io/gorm"

	"bbs-go/internal/models"
	"bbs-go/internal/repositories"
)

var ChatGroupsMembersService = newChatGroupsMembersService()

func newChatGroupsMembersService() *chatGroupsMembersService {
	return &chatGroupsMembersService{}
}

type chatGroupsMembersService struct {
}

func (s *chatGroupsMembersService) Get(id int64) *models.ChatGroupsMembers {
	return repositories.ChatGroupsMembersRepository.Get(sqls.DB(), id)
}

func (s *chatGroupsMembersService) Take(where ...interface{}) *models.ChatGroupsMembers {
	return repositories.ChatGroupsMembersRepository.Take(sqls.DB(), where...)
}

func (s *chatGroupsMembersService) Find(cnd *sqls.Cnd) []models.ChatGroupsMembers {
	return repositories.ChatGroupsMembersRepository.Find(sqls.DB(), cnd)
}

func (s *chatGroupsMembersService) FindPageByParams(params *params.QueryParams) (list []models.ChatGroupsMembers, paging *sqls.Paging) {
	return repositories.ChatGroupsMembersRepository.FindPageByParams(sqls.DB(), params)
}

func (s *chatGroupsMembersService) FindPageByCnd(cnd *sqls.Cnd) (list []models.ChatGroupsMembers, paging *sqls.Paging) {
	return repositories.ChatGroupsMembersRepository.FindPageByCnd(sqls.DB(), cnd)
}

func (s *chatGroupsMembersService) Create(t *models.ChatGroupsMembers) error {
	return repositories.ChatGroupsMembersRepository.Create(sqls.DB(), t)
}

func (s *chatGroupsMembersService) Update(t *models.ChatGroupsMembers) error {
	return repositories.ChatGroupsMembersRepository.Update(sqls.DB(), t)
}

func (s *chatGroupsMembersService) Updates(id int64, columns map[string]interface{}) error {
	return repositories.ChatGroupsMembersRepository.Updates(sqls.DB(), id, columns)
}

func (s *chatGroupsMembersService) UpdateColumn(id int64, name string, value interface{}) error {
	return repositories.ChatGroupsMembersRepository.UpdateColumn(sqls.DB(), id, name, value)
}

func (s *chatGroupsMembersService) DeleteByArticleId(articleId int64) {
	sqls.DB().Model(models.ChatGroupsMembers{}).Where("article_id = ?", articleId).UpdateColumn("status", constants.StatusDeleted)
}

func (s *chatGroupsMembersService) FindChatGroupsMembersByGroupUserId(groupId, userId int64) (models.ChatGroupsMembers, error) {
	chatGroupsMembers := models.ChatGroupsMembers{}
	err := sqls.DB().Model(&models.ChatGroupsMembers{}).Where("group_id = ? and user_id = ?", groupId, userId).First(&chatGroupsMembers).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return models.ChatGroupsMembers{}, err
	}

	return chatGroupsMembers, nil
}

// 查询群组成员
func (s *chatGroupsMembersService) GetChatGroupsMembersList(page *sqls.Paging, groupId int64) (models.ChatGroupsMembersListResponse, error) {
	limit := page.Limit
	offset := page.Limit * (page.Page - 1)
	if limit == 0 {
		limit = 10
	}
	db := sqls.DB()
	querySql := `select cgm.*,
	tu.nickname as user_nickname,tu.avatar as user_avatar,tu.email as user_email,tu.username as username
	from chat_groups_members cgm 
	left join t_user tu on cgm.user_id = tu.id
	where 1=1 and cgm.deleted_at is null `
	whereSql := ""
	whereVars := []interface{}{}

	whereSql += " and cgm.group_id = ? "
	whereVars = append(whereVars, groupId)

	countSql := `select count(1)
	from chat_groups_members cgm  
	where 1=1 `

	var total int64
	err := db.Raw(countSql+whereSql, whereVars...).Scan(&total).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return models.ChatGroupsMembersListResponse{}, err
	}

	list := []models.ChatGroupsMembersResponse{}
	orderBySql := " order by cgm.created_at asc LIMIT " + strconv.Itoa(limit) + " OFFSET " + strconv.Itoa(offset)
	err = db.Raw(querySql+whereSql+orderBySql, whereVars...).Find(&list).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return models.ChatGroupsMembersListResponse{}, err
	}

	return models.ChatGroupsMembersListResponse{
		List: list,
		Paging: &sqls.Paging{
			Page:  page.Page,
			Limit: page.Limit,
			Total: total,
		},
	}, nil
}

func (s *chatGroupsMembersService) Add(groupId int64, groupName string, friendId int64) error {
	tx := sqls.DB().Begin()
	err := tx.Create(&models.ChatGroupsMembers{
		GroupId:   groupId,
		GroupName: groupName,
		UserId:    friendId,
		RoleId:    consts.ChatGroupsMembersRoleId_1,
	}).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Model(&models.ChatGroupsMembersUnreadMessage{
		GroupId: groupId,
		UserId:  friendId,
		UnRead:  false,
	}).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Commit().Error
	if err != nil {
		tx.Rollback()
		return err
	}

	return nil
}

func (s *chatGroupsMembersService) FindChatGroupsMemberIdsByGroupId(groupId int) (membersId []int, err error) {
	err = sqls.DB().Model(&models.ChatGroupsMembers{}).Where("group_id = ? ", groupId).Select("user_id").Scan(&membersId).Error
	return membersId, err
}

// 移除群组某个人
func (s *chatGroupsMembersService) Remove(groupId int64, usersId int64) error {
	tx := sqls.DB().Begin()
	err := tx.Delete(&models.ChatGroupsMembers{}, "group_id = ? and user_id = ?", groupId, usersId).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Delete(&models.ChatGroupsMembersUnreadMessage{}, "group_id = ? and user_id = ?", groupId, usersId).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Commit().Error
	if err != nil {
		tx.Rollback()
		return err
	}
	return nil
}

func (s *chatGroupsMembersService) UpdateMeberRole(groupId int64, memberId, memberRoleId int64) error {
	return sqls.DB().Model(&models.ChatGroupsMembers{}).Where("group_id = ? and user_id = ?", groupId, memberId).Update("role_id", memberRoleId).Error
}

func (s *chatGroupsMembersService) Exit(chatGroupsMember models.ChatGroupsMembers) error {
	tx := sqls.DB().Begin()
	err := tx.Delete(&models.ChatGroupsMembers{}, "id = ? ", chatGroupsMember.Id).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Delete(&models.ChatGroupsMembersUnreadMessage{}, "group_id = ? and user_id = ?", chatGroupsMember.GroupId, chatGroupsMember.UserId).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	err = tx.Commit().Error
	if err != nil {
		tx.Rollback()
		return err
	}
	return nil
}
